/**
 * Copyright (C) 2013 Oleg Anastassov <oleg.anastassov@gmail.com>
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package kz.kstu.loc.business.extract.strategy;

import kz.kstu.loc.entity.Item;
import kz.kstu.loc.util.StringUtils;
import kz.kstu.loc.util.logger.Logger;

import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

/**
 * Стратегия извлечения текстовок из файлов, хранящих информацию в формате:
 * <pre>
 *     ключ=значение
 * </pre>
 * <p/>
 * Date: 17.01.2013
 * Time: 13:15
 *
 * @author Oleg Anastassov
 */
public class PropertiesExtractStrategy implements ExtractStrategy {

    private static final Logger LOGGER = Logger.getLogger(PropertiesExtractStrategy.class);

    private static final String DEFAULT_PREFIX = "^";

    private String prefix;

    public PropertiesExtractStrategy() {
    }

    public PropertiesExtractStrategy(String prefix) {
        this.prefix = prefix;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Item> extract(File file) {
        LOGGER.info("Start process ''{0}'' file.", file.getAbsolutePath());
        Properties p = read(file);

        prefix = prefix != null ? prefix : DEFAULT_PREFIX;
        LOGGER.info("Use ''{0}'' as prefix.", prefix);

        List<Item> items = new ArrayList<Item>();
        Enumeration em = p.keys();
        while (em.hasMoreElements()) {
            String key = (String) em.nextElement();
            String val = p.getProperty(key);


            if (val.startsWith(prefix)) {
                val = val.substring(1); // избавляемя от префикса
                LOGGER.info("Matched key=''{0}'', value=''{1}'';", key, val);
                items.add(new Item(key, val, StringUtils.EMPTY_STRING));
            }
        }
        if (items.isEmpty()) {
            LOGGER.warn("There are no extracted items. Result list is empty.");
        } else {
            LOGGER.info("Total extracted items={0}", items.size());
        }
        LOGGER.info("End process ''{0}'' file.", file.getAbsolutePath());
        return items;
    }

    private Properties read(File file) {
        try {
            Properties p = new Properties();
            InputStream in = new FileInputStream(file);
            p.load(in);
            in.close();
            return toUTF8(p);
        } catch (FileNotFoundException e) {
            LOGGER.error("File not found: ", e);
        } catch (IOException e) {
            LOGGER.error("I/O error: ", e);
        }
        return new Properties();
    }

    /**
     * Фикс кодировки для корректного чтения
     * символов русского алфавита.
     * <p/>
     * Загрузка файлов 'properties' через поток
     * идет в кодировке ISO-8859-1.
     *
     * @return файл со значениями в кодировке UTF-8
     */
    private Properties toUTF8(Properties p) {
        try {
            Properties fixedProps = new Properties();
            Enumeration em = p.keys();
            while (em.hasMoreElements()) {
                String key = (String) em.nextElement();
                String val = p.getProperty(key);
                fixedProps.put(key, new String(val.getBytes("ISO-8859-1"), "UTF-8"));
            }
            return fixedProps;
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("Unsupported encoding: ", e);
        }
        return p;
    }

}
